package com.ts.enterprise.common.utils;

import cn.hutool.core.text.StrBuilder;
import com.ts.enterprise.common.response.BaseResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;

/***
 * 微信API请求工具类
 * 还要考虑token的问题
 * 首先，token调用应该是无感的
 * 其次token接口是不能频繁调用的，否则会收到频率拦截,而且失效时间不可控，之后会放入redis进行统一管理
 * 这边就涉及到了刷新策略，建议被动刷新
 */
public class RestTemplateUtils {
    private static RestTemplate restTemplate = new RestTemplate();

    private static Logger logger = LoggerFactory.getLogger(RestTemplateUtils.class);

    public static String get(String uri, Map<String, Object> params, boolean requireToken) {
        String url = (params == null || params.isEmpty()) ? uri : uri + "?" + params.keySet().stream().filter(x -> params.get(x) != null).map(x -> x + "=" + params.get(x)).reduce((x, y) -> x + "&" + y).get();
        String res = restTemplate.getForObject(url, String.class);
        return res;
    }


    public static String post(String uri, Map<String, Object> params, MediaType type, String body, boolean requireToken) {
        //去除 filter(x -> params.get(x) != null) 防止报错  --yunjun
        String url = (params == null || params.isEmpty()) ? uri : uri + "?" + params.keySet().stream().map(x -> x + "=" + params.get(x)).reduce((x, y) -> x + y).get();
        HttpHeaders headers = new HttpHeaders();
        MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
        headers.setContentType(mediaType);
        HttpEntity<String> entity = new HttpEntity<>(body, headers);
        RestTemplate restTemplate = new RestTemplate();
        StrBuilder sb = new StrBuilder(uri);
        sb.append(appendParams(params));
        return restTemplate.postForObject(url, entity, String.class);
    }

    public static <T> T post(String uri, Map<String, Object> params, MediaType type, String body, boolean requireToken, Class<T> T) {
        //去除 filter(x -> params.get(x) != null) 防止报错  --yunjun
        String url = (params == null || params.isEmpty()) ? uri : uri + "?" + params.keySet().stream().map(x -> x + "=" + params.get(x)).reduce((x, y) -> x + y).get();
        HttpHeaders headers = new HttpHeaders();
        MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
        headers.setContentType(mediaType);
        HttpEntity<String> entity = new HttpEntity<>(body, headers);
        RestTemplate restTemplate = new RestTemplate();
        StrBuilder sb = new StrBuilder(uri);
        sb.append(appendParams(params));
        return restTemplate.postForObject(url, entity, T);
    }

    /**
     * 获取access_token
     *
     * @param uri    地址
     * @param params 参数
     * @return
     */
    public static BaseResponse get(String uri, Map<String, Object> params) {
        StringBuilder sb = new StringBuilder(uri);
        sb.append(appendParams(params));
        return restTemplate.getForObject(sb.toString(), BaseResponse.class);
    }

    public static BaseResponse get(String uri, Map<String, Object> params, Class<? extends BaseResponse> clazz) {
        StringBuilder sb = new StringBuilder(uri);
        sb.append(appendParams(params));
        return restTemplate.getForObject(sb.toString(), clazz);
    }

    public static BaseResponse post(String uri, Map<String, Object> params, String body) {
        //设置utf-8 防止中文乱码
        HttpHeaders headers = new HttpHeaders();
        MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
        headers.setContentType(mediaType);
        HttpEntity<String> entity = new HttpEntity<>(body, headers);
        RestTemplate restTemplate = new RestTemplate();
        StrBuilder sb = new StrBuilder(uri);
        sb.append(appendParams(params));
        return restTemplate.postForObject(sb.toString(), entity, BaseResponse.class);
    }

    public static BaseResponse post(String uri, Map<String, Object> params, String body, Class<? extends BaseResponse> clazz) {
        //设置utf-8 防止中文乱码
        HttpHeaders headers = new HttpHeaders();
        MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
        headers.setContentType(mediaType);
        HttpEntity<String> entity = new HttpEntity<>(body, headers);
        RestTemplate restTemplate = new RestTemplate();
        StrBuilder sb = new StrBuilder(uri);
        sb.append(appendParams(params));
        return restTemplate.postForObject(sb.toString(), entity, clazz);
    }

    public static String postJSONBody(String uri, Map<String, Object> params, String basicAuth, String body) throws Exception {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        if (basicAuth != null){
            httpHeaders.setBasicAuth(basicAuth);
        }
        StrBuilder sb = new StrBuilder(uri);
        sb.append(appendParams(params));
        HttpEntity<String> httpEntity = new HttpEntity<>(body, httpHeaders);
        logger.info("url---{}", sb.toString());
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(new URI(sb.toString()), httpEntity, String.class);
        String result = responseEntity.getBody();
        logger.info("responseEntity:{}", responseEntity);
        return result;
    }

    public static Object postObjectBody(String uri, Map<String, Object> params, String body) throws Exception {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
        StrBuilder sb = new StrBuilder(uri);
        sb.append(appendParams(params));
        HttpEntity<Object> httpEntity = new HttpEntity<>(body, httpHeaders);
        logger.info("url---{}", sb.toString());
        ResponseEntity<Object> responseEntity = restTemplate.postForEntity(new URI(sb.toString()), httpEntity, Object.class);
        Object result = responseEntity.getBody();
        logger.info("responseEntity:{}", responseEntity);
        return result;
    }


    /**
     * 拼接请求参数
     *
     * @param params
     * @return
     */
    public static String appendParams(Map<String, Object> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder("?");
        Iterator<String> iterator = params.keySet().iterator();
        while (iterator.hasNext()) {
            String currentKey = iterator.next();
            Object currentValue = params.get(currentKey);
            if (currentValue == null) {
                continue;
            }
            sb.append(currentKey);
            sb.append("=");
            sb.append(params.get(currentKey));
            if (iterator.hasNext()) {
                sb.append("&");
            }
        }
        return sb.equals("?") ? "" : sb.toString();
    }
}
